<!DOCTYPE html>
            
<HTML>
<HEAD>
<meta name="booktitle" content="Developing Applications With Objective Caml" >
 <meta charset="ISO-8859-1"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<META name="GENERATOR" content="hevea 1.05-7 of 2000-02-24">
<META NAME="Author" CONTENT="Christian.Queinnec@lip6.fr">
<LINK rel=stylesheet type="text/css" href="videoc-ocda.css">
<script language="JavaScript" src="videoc.js"><!--
//--></script>
<TITLE>
 Exercises
</TITLE>
</HEAD>
<BODY class="regularBody">
<A HREF="book-ora118.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora120.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2> Exercises</H2><A NAME="toc163"></A>
<H3> Polymorphic Printing Function</H3>
We wish to define a printing function <TT>print</TT> with type
<I>'a -&gt; unit</I> able to print any Objective CAML value. To this end, we
extend and improve the <TT>inspect</TT> function.<BR>
<BR>
<OL type=1>
<LI>
 In C, write the <A id="a228__1_APPEND/ICcor.ml.tex" href="javascript: void showMessage('1_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 1,APPEND/ICcor.ml.tex,printws -->function</SPAN></A> <TT>print_ws</TT> 
which prints Objective CAML as follows:
<UL>
<LI>
 immediate values: as C integers;

<LI> strings: between quotes;

<LI> floats: as usual;

<LI> arrays of floats: between <TT>[| |]</TT>

<LI> closures: as <CODE>&lt; code, env &gt;</CODE>

<LI> everything else: as a tuple, between <TT>( )</TT>
</UL>
The function should handle structured types recursively.
<!-- POPUP DEFINITION -->
<layer id="l__1_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","1_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 A polymorphic printing function in C:
<PRE>
#include &lt;stdio.h&gt;
#include &lt;caml/mlvalues.h&gt;
#include &lt;caml/memory.h&gt;

value print_ws (value v) {
  CAMLparam1(v);
  int size,i ;
  if (Is_long(v)) printf("%d", Long_val(v)); 
  else {
    size=Wosize_val(v);
    switch (Tag_val(v)) 
      {
      case String_tag :
 printf("\"%s\"", String_val(v));  
 break;
      case Double_tag:  
 printf("%g", Double_val(v));
 break;
      case Double_array_tag : 
 printf ("[|"); 
        if (size&gt;0) printf("%g", Double_field(v,0));
 for (i=1;i&lt;(size/Double_wosize);i++)  printf("; %g", Double_field(v,i));
 printf("|]");
 break;
      case Abstract_tag :
      case Custom_tag : 
 printf("&lt;abstract&gt;"); 
 break;
      case Closure_tag : 
 printf("&lt;%d, ",Code_val(v)) ;
 if (size&gt;1) print_ws(Field(v,1)) ;
 for (i=2;i&lt;size;i++) {
   printf("; ") ;
   print_ws(Field(v,i));
 }
 printf("&gt;");
 break;
      default:  
 if (Tag_val(v)&gt;=No_scan_tag) printf("?"); 
 else {
   printf("(");
   if (size&gt;0) print_ws(Field(v,0));
   for (i=1;i&lt;size;i++) {
     printf(", ");
     print_ws(Field(v,i));
   }
   printf(")");
 }
      }
  }
  fflush(stdout);
  return Val_unit;
}
</PRE>called from Objective CAML:


<PRE><BR># <B>external</B><CODE> </CODE>print_ws<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>-&gt;<CODE> </CODE>unit<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>"print_ws"</CODE><CODE> </CODE><CODE> </CODE>;;<BR><CODE>external print_ws : 'a -&gt; unit = "print_ws"</CODE><BR>

</PRE>

</span><script language="JavaScript"><!--
  closePopUp("1_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script><BR>
<BR>

<LI> To avoid looping on circular values, and to display sharing
properly, modify this function to keep track of the addresses of heap
blocks it has already seen. If an <A id="a229__2_APPEND/ICcor.ml.tex" href="javascript: void showMessage('2_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 2,APPEND/ICcor.ml.tex,address -->address</SPAN></A> appears several 
times, name it when it is first printed (<TT>v = name</TT>), and just
print the name when this address is encountered again.
<!-- POPUP DEFINITION -->
<layer id="l__2_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","2_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 

<PRE><BR># <B>type</B><CODE> </CODE>address<CODE> </CODE>;;<BR><CODE>type address</CODE><BR>

</PRE>

</span><script language="JavaScript"><!--
  closePopUp("2_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script><OL type=a>
<LI>
 Define a data <A id="a230__3_APPEND/ICcor.ml.tex" href="javascript: void showMessage('3_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 3,APPEND/ICcor.ml.tex,adrstruct -->structure</SPAN></A>  
to <A id="a231__4_APPEND/ICcor.ml.tex" href="javascript: void showMessage('4_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 4,APPEND/ICcor.ml.tex,adrstock -->record</SPAN></A> the addresses, <A id="a232__5_APPEND/ICcor.ml.tex" href="javascript: void showMessage('5_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 5,APPEND/ICcor.ml.tex,adrdenote -->determine</SPAN></A> when  
they occur several times, and <A id="a233__6_APPEND/ICcor.ml.tex" href="javascript: void showMessage('6_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 6,APPEND/ICcor.ml.tex,adrassoc -->associate</SPAN></A> a name with each address. 
<!-- POPUP DEFINITION -->
<layer id="l__3_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","3_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 

<PRE><BR># <B>let</B><CODE> </CODE><TT>(</TT>gensym<CODE>,</CODE>init_gensym<TT>)</TT><CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>i<CODE> </CODE><CODE>=</CODE><CODE> </CODE>ref<CODE> </CODE><CODE>0</CODE><CODE> </CODE><B>in</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><B>function</B><CODE> </CODE>()<CODE> </CODE>-&gt;<CODE> </CODE>incr<CODE> </CODE>i<CODE> </CODE>;<CODE> </CODE><CODE>"val_"</CODE><CODE> </CODE><CODE>^</CODE><CODE> </CODE><TT>(</TT>string_of_int<CODE> </CODE><CODE>!</CODE>i<TT>)</TT><TT>)</TT><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>,</CODE><CODE> </CODE><TT>(</TT><B>function</B><CODE> </CODE>()<CODE> </CODE>-&gt;<CODE> </CODE>i<CODE>:=</CODE><CODE>0</CODE><TT>)</TT><CODE> </CODE>;;<BR><CODE>val gensym : unit -&gt; string = &lt;fun&gt;</CODE><BR><CODE>val init_gensym : unit -&gt; unit = &lt;fun&gt;</CODE><BR><BR># <B>type</B><CODE> </CODE>occurrence<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Once<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>Several_times<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>Already_named<CODE> </CODE><B>of</B><CODE> </CODE>string<CODE> </CODE>;;<BR><CODE>type occurrence = | Once | Several_times | Already_named of string</CODE><BR><BR># <B>let</B><CODE> </CODE>table<CODE> </CODE><CODE>=</CODE><CODE> </CODE>ref<CODE> </CODE><TT>(</TT>[]<CODE> </CODE><CODE>:</CODE><CODE> </CODE><TT>(</TT>address<CODE> </CODE><CODE>*</CODE><CODE> </CODE>occurrence<TT>)</TT><CODE> </CODE>list<TT>)</TT><CODE> </CODE>;;<BR><CODE>val table : (address * occurrence) list ref = {contents=[]}</CODE><BR>

</PRE>

</span><script language="JavaScript"><!--
  closePopUp("3_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<!-- POPUP DEFINITION -->
<layer id="l__4_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","4_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 

<PRE><BR># <B>let</B><CODE> </CODE>record<CODE> </CODE>addr<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>try</B><CODE> </CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>match</B><CODE> </CODE>List.assq<CODE> </CODE>addr<CODE> </CODE><CODE>!</CODE>table<CODE> </CODE><B>with</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Once<CODE> </CODE>-&gt;<CODE> </CODE>table<CODE> </CODE><CODE>:=</CODE><CODE> </CODE><TT>(</TT>addr<CODE>,</CODE><CODE> </CODE>Several_times<TT>)</TT><CODE> </CODE>::<CODE> </CODE><CODE>!</CODE>table;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>true</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE>-&gt;<CODE> </CODE><B>true</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>with</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Not_found<CODE> </CODE>-&gt;<CODE> </CODE>table<CODE> </CODE><CODE>:=</CODE><CODE> </CODE><TT>(</TT>addr<CODE>,</CODE><CODE> </CODE>Once<TT>)</TT><CODE> </CODE>::<CODE> </CODE><CODE>!</CODE>table;<CODE> </CODE><B>false</B><CODE> </CODE>;;<BR><CODE>val record : address -&gt; bool = &lt;fun&gt;</CODE><BR>

</PRE>

</span><script language="JavaScript"><!--
  closePopUp("4_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<!-- POPUP DEFINITION -->
<layer id="l__5_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","5_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 

<PRE><BR># <B>let</B><CODE> </CODE>multiple_occ<CODE> </CODE>addr<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>match</B><CODE> </CODE>List.assq<CODE> </CODE>addr<CODE> </CODE><CODE>!</CODE>table<CODE> </CODE><B>with</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Once<CODE> </CODE>-&gt;<CODE> </CODE><B>false</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE>-&gt;<CODE> </CODE><B>true</B><CODE> </CODE>;;<BR><CODE>val multiple_occ : address -&gt; bool = &lt;fun&gt;</CODE><BR>

</PRE>

</span><script language="JavaScript"><!--
  closePopUp("5_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<!-- POPUP DEFINITION -->
<layer id="l__6_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","6_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 

<PRE><BR># <B>let</B><CODE> </CODE>already_named<CODE> </CODE>addr<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>match</B><CODE> </CODE>List.assq<CODE> </CODE>addr<CODE> </CODE><CODE>!</CODE>table<CODE> </CODE><B>with</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Once<CODE> </CODE>-&gt;<CODE> </CODE>failwith<CODE> </CODE><CODE>"already_named"</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>Several_times<CODE> </CODE>-&gt;<CODE> </CODE>table<CODE> </CODE><CODE>:=</CODE><CODE> </CODE><TT>(</TT>addr<CODE>,</CODE><CODE> </CODE>Already_named<CODE> </CODE><TT>(</TT>gensym<CODE> </CODE>()<TT>)</TT><TT>)</TT><CODE> </CODE>::<CODE> </CODE><CODE>!</CODE>table;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>false</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>Already_named<CODE> </CODE><CODE>_</CODE><CODE> </CODE>-&gt;<CODE> </CODE><B>true</B><CODE> </CODE>;;<BR><CODE>val already_named : address -&gt; bool = &lt;fun&gt;</CODE><BR><BR># <B>let</B><CODE> </CODE>name_of<CODE> </CODE>addr<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>match</B><CODE> </CODE>List.assq<CODE> </CODE>addr<CODE> </CODE><CODE>!</CODE>table<CODE> </CODE><B>with</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Already_named<CODE> </CODE>s<CODE> </CODE>-&gt;<CODE> </CODE>s<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE>-&gt;<CODE> </CODE>raise<CODE> </CODE>Not_found<CODE> </CODE>;;<BR><CODE>val name_of : address -&gt; string = &lt;fun&gt;</CODE><BR>

</PRE>

</span><script language="JavaScript"><!--
  closePopUp("6_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script>
<LI> <A id="a234__7_APPEND/ICcor.ml.tex" href="javascript: void showMessage('7_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 7,APPEND/ICcor.ml.tex,cadr -->Traverse</SPAN></A> the value once first to determine all the 
addresses it contains and record them in the data structure.
<!-- POPUP DEFINITION -->
<layer id="l__7_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","7_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 La partie Objective CAML:


<PRE><BR># Callback.register<CODE> </CODE><CODE>"add"</CODE><CODE> </CODE>ajoute<CODE> </CODE>;;<BR><CODE>- : unit = ()</CODE><BR># Callback.register<CODE> </CODE><CODE>"multiple?"</CODE><CODE> </CODE>multiple_occ<CODE> </CODE>;;<BR><CODE>- : unit = ()</CODE><BR># Callback.register<CODE> </CODE><CODE>"named?"</CODE><CODE> </CODE>already_named<CODE> </CODE>;;<BR><CODE>- : unit = ()</CODE><BR># Callback.register<CODE> </CODE><CODE>"name"</CODE><CODE> </CODE>name_of<CODE> </CODE>;;<BR><CODE>- : unit = ()</CODE><BR><BR># <B>external</B><CODE> </CODE>explore_value<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>-&gt;<CODE> </CODE>unit<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>"explore"</CODE><CODE> </CODE><CODE> </CODE>;;<BR><CODE>external explore_value : 'a -&gt; unit = "explore"</CODE><BR>

</PRE>

The C part:
<PRE>
#include &lt;caml/callback.h&gt;

value explore (value v) {
  CAMLparam1(v);
  int size,i;
  if (Is_long(v)) return Val_unit;
  if (Bool_val(callback(*caml_named_value("add"), v))) return Val_unit;
  size=Wosize_val(v);
  switch (Tag_val(v)) 
    {
      case String_tag :
      case Double_tag:  
      case Double_array_tag : 
      case Abstract_tag :
      case Final_tag : 
        break;
      case Closure_tag : 
        for (i=1;i&lt;size;i++) explore(Field(v,i));
        break;
      default:  
        if (Tag_val(v)&gt;=No_scan_tag) break ;
        for (i=0;i&lt;size;i++) explore(Field(v,i));
    }
  return Val_unit;
}
</PRE></span><script language="JavaScript"><!--
  closePopUp("7_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script>
<LI> The second traversal <A id="a235__8_APPEND/ICcor.ml.tex" href="javascript: void showMessage('8_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 8,APPEND/ICcor.ml.tex,camladr -->prints</SPAN></A> the value 
while naming addresses at their first occurrences.
<!-- POPUP DEFINITION -->
<layer id="l__8_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","8_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 

<PRE><BR># <B>external</B><CODE> </CODE>print_rec<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>-&gt;<CODE> </CODE>unit<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>"print_gen"</CODE><CODE> </CODE>;;<BR><CODE>external print_rec : 'a -&gt; unit = "print_gen"</CODE><BR>

</PRE>

<PRE>
value print_gen (value v)
{
  CAMLparam1(v);
  int size,i ;
  if (Is_long(v))  return print_ws(v) ;
  if (Bool_val(callback(*caml_named_value("multiple?"),v))) {
    if (Bool_val(callback(*caml_named_value("named?"),v))) {
      printf("%s",String_val(callback(*caml_named_value("name"),v))) ;
      return Val_unit ;
    }
    printf("%s = { ",String_val(callback(*caml_named_value("name"),v))) ;
  }
  size=Wosize_val(v);
  switch (Tag_val(v)) 
    {
      case String_tag :
      case Double_tag:  
      case Double_array_tag : 
      case Abstract_tag :
      case Final_tag : 
 print_ws(v);
 break;
      case Closure_tag : 
 printf("&lt;%d, ",Code_val(v)) ;
 if (size&gt;1) print_gen(Field(v,1)) ;
 for (i=2;i&lt;size;i++) {
   printf("; ") ;
   print_gen(Field(v,i));
 }
 printf("&gt;");
 break;
      default:  
 if (Tag_val(v)&gt;=No_scan_tag) printf("?"); 
 else {
   printf("(");
   if (size&gt;0) print_gen(Field(v,0));
   for (i=1;i&lt;size;i++) {
     printf(", ");
     print_gen(Field(v,i));
   }
   printf(")");
 }
    }
  if (Bool_val(callback(*caml_named_value("multiple?"),v)))  printf(" }") ; 
  fflush(stdout);
  return Val_unit;
}
</PRE></span><script language="JavaScript"><!--
  closePopUp("8_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script>
<LI> Define the function <TT><A id="a236__9_APPEND/ICcor.ml.tex" href="javascript: void showMessage('9_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 9,APPEND/ICcor.ml.tex,printadr -->print</SPAN></A></TT>  
combining both traversals.
<!-- POPUP DEFINITION -->
<layer id="l__9_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","9_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 

<PRE><BR><B>external</B><CODE> </CODE>print_rec<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>-&gt;<CODE> </CODE>unit<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>"print_gen"</CODE><CODE> </CODE>;;<BR><B>let</B><CODE> </CODE>print<CODE> </CODE>v<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE>table<CODE> </CODE><CODE>:=</CODE><CODE> </CODE>[]<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE>init_gensym<CODE> </CODE>()<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE>explore_value<CODE> </CODE>v<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE>print_rec<CODE> </CODE>v<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE>table<CODE> </CODE><CODE>:=</CODE><CODE> </CODE>[]<CODE> </CODE>;;<BR>

</PRE>

</span><script language="JavaScript"><!--
  closePopUp("9_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script></OL>
</OL> <A NAME="toc164"></A>
<H3> Matrix Product</H3>
<OL type=1>
<LI>
 Define an <A id="a237__10_APPEND/ICcor.ml.tex" href="javascript: void showMessage('10_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 10,APPEND/ICcor.ml.tex,abstract-type -->abstract type</SPAN></A> <I>float_matrix</I>  
for matrices of floating-point numbers.
<!-- POPUP DEFINITION -->
<layer id="l__10_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","10_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 

<PRE><BR># <B>type</B><CODE> </CODE>float_matrix<CODE> </CODE>;;<BR><CODE>type float_matrix</CODE><BR>

</PRE>

</span><script language="JavaScript"><!--
  closePopUp("10_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script><BR>
<BR>

<LI> Define a <A id="a238__11_APPEND/ICcor.ml.tex" href="javascript: void showMessage('11_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 11,APPEND/ICcor.ml.tex,type-C -->C type</SPAN></A> for these matrices. 
<!-- POPUP DEFINITION -->
<layer id="l__11_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","11_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 <PRE>
typedef struct { void (*finalization_function)(value) ;
                 int size_x , size_y ;
                 double * mat ;
               } Matrix ;
</PRE></span><script language="JavaScript"><!--
  closePopUp("11_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script><BR>
<BR>

<LI> Write a C function to <A id="a239__12_APPEND/ICcor.ml.tex" href="javascript: void showMessage('12_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 12,APPEND/ICcor.ml.tex,convC -->convert</SPAN></A> values of type 
<I>float array array</I> to values of type
<I>float_matrix</I>. 
<!-- POPUP DEFINITION -->
<layer id="l__12_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","12_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 <PRE>
static void finalize_matrix(value mat) {
  free(((Matrix *) mat)-&gt;mat);
}

static value alloc_matrix(int size_x,int size_y) {
  int byte_size ;
  Matrix * res ;
  vres=alloc(sizeof(Matrix)/sizeof(value),
             finalize_matrix, size_x*size_y, 1000000) ;
  res=(Matrix *) vres ;
  res-&gt;size_x = size_x ;
  res-&gt;size_y = size_y ;
  res-&gt;mat = malloc(size_x*size_y*sizeof(double)) ;
  return vres;
}

value conversion_to_C (value faa) {
  CAMLparam1(faa) ;
  CAMLlocal2(vres,vect) ;
  Matrix * res ;
  double * tab;
  int size_x, size_y, i, j ;

  /* size of the array of arrays */
  size_x = Wosize_val(faa) ;
  /* size of each array */
  if (size_x&gt;0) size_y = Wosize_val(Field(faa,0))/2 ;

  /* allocate the value of type float_matrix */
  vres=alloc_matrix(size_x,size_y);
  res=(Matrix *) vres ;
  res-&gt;size_x = size_x ;
  res-&gt;size_y = size_y ;
  tab = res-&gt;mat;
  for (i=0;i&lt;size_x;i++) {
    vect = Field(faa,i) ;
    if (Wosize_val(vect) != size_y)
      failwith("non-rectangular float array array") ;
    for (j=0;j&lt;size_y;j++) *tab++ = Double_field(vect,j) ;
    }
  }
  CAMLreturn vres ;
}
</PRE></span><script language="JavaScript"><!--
  closePopUp("12_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script><BR>
<BR>

<LI> Write a C function performing the <A id="a240__13_APPEND/ICcor.ml.tex" href="javascript: void showMessage('13_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 13,APPEND/ICcor.ml.tex,convCAML -->reverse</SPAN></A> conversion.  
<!-- POPUP DEFINITION -->
<layer id="l__13_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","13_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 <PRE>
value conversion_to_Caml (value matrix) {
  CAMLparam1(matrix) ;
  CAMLlocal2(res,aux) ;
  Matrix* mat = (Matrix *) matrix ;
  float * tab = mat-&gt;mat ;
  int i,j ;
  res=alloc(mat-&gt;size_x,0);
  for (i=0;i&lt;mat-&gt;size_x;i++) {
    aux = alloc(mat-&gt;size_y*Double_wosize,Double_array_tag) ;
    Store_field(res,i,aux);
    for (j=0;j&lt;mat-&gt;size_y;j++) Store_double_field(aux,j,*tab++) ;
  }
  CAMLreturn res ;
}
</PRE></span><script language="JavaScript"><!--
  closePopUp("13_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script><BR>
<BR>

<LI> Add the C functions computing the <A id="a241__14_APPEND/ICcor.ml.tex" href="javascript: void showMessage('14_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 14,APPEND/ICcor.ml.tex,matriceadd -->sum</SPAN></A>  
and the <A id="a242__15_APPEND/ICcor.ml.tex" href="javascript: void showMessage('15_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 15,APPEND/ICcor.ml.tex,matriceprod -->product</SPAN></A> of these matrices. 
<!-- POPUP DEFINITION -->
<layer id="l__14_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","14_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 <PRE>
value matrix_sum (value arg1,value arg2) {
  CAMLparam2(arg1,arg2) ;
  CAMLlocal1(vres) ;
  Matrix *m1=(Matrix*) arg1, *m2=(Matrix*) arg2, *res;
  int size,i;
  if (m1-&gt;size_x != m2-&gt;size_x || m1-&gt;size_y != m2-&gt;size_y)
    failwith("illegal matrix addition");
  vres=alloc_matrix(m1-&gt;size_x,m1-&gt;size_y);
  res =(Matrix*) vres;
  tab=vres-&gt;mat;
  size=m1-&gt;size_x*m1-&gt;size_y;
  for (i=0;i&lt;size;i++) tab[i]=m1-&gt;mat[i]+m2-&gt;mat[i] ;
  CAMLreturn vres;
}
</PRE></span><script language="JavaScript"><!--
  closePopUp("14_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<!-- POPUP DEFINITION -->
<layer id="l__15_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","15_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 <PRE>
value matrix_product (value arg1,value arg2) {
  CAMLparam2(arg1,arg2) ;
  CAMLlocal1(vres) ;
  Matrix *m1=(Matrix*) arg1, *m2=(Matrix*) arg2, *res;
  int i,j,k;
  if (m1-&gt;size_y != m2-&gt;size_x) failwith("illegal matrix product");
  vres=alloc_matrix(m1-&gt;size_x,m2-&gt;size_y);
  for (i=0;i&lt;res-&gt;size_x;i++) 
    for (j=0;j&lt;res-&gt;size_y;j++) {
      double acc=0 ;
      for (k=0;k&lt;m1-&gt;size_y;k++) 
 acc += m1-&gt;mat[i*m1-&gt;size_x+k] * m1-&gt;mat[k*m2-&gt;size_x+j] ;
      tab[i*m1-&gt;size_x+j]=acc ;
    }
  CAMLreturn vres;
}
</PRE></span><script language="JavaScript"><!--
  closePopUp("15_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script><script language="JavaScript"><!--
  initializePreviousHints();
// --></script><BR>
<BR>

<LI> <A id="a243__16_APPEND/ICcor.ml.tex" href="javascript: void showMessage('16_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 16,APPEND/ICcor.ml.tex,matriceinterface -->Interface</SPAN></A> them with Objective CAML and use them. 
<!-- POPUP DEFINITION -->
<layer id="l__16_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","16_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 

<PRE><BR># <B>external</B><CODE> </CODE>to_matrix<CODE> </CODE><CODE>:</CODE><CODE> </CODE>float<CODE> </CODE>array<CODE> </CODE>array<CODE> </CODE>-&gt;<CODE> </CODE>float_matrix<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>"conversion_to_C"</CODE><CODE> </CODE>;;<BR># <B>external</B><CODE> </CODE>of_matrix<CODE> </CODE><CODE>:</CODE><CODE> </CODE>float_matrix<CODE> </CODE>-&gt;<CODE> </CODE>float<CODE> </CODE>array<CODE> </CODE>array<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>"conversion_to_Caml"</CODE>;;<BR># <B>external</B><CODE> </CODE>sum<CODE> </CODE><CODE>:</CODE><CODE> </CODE>float_matrix<CODE> </CODE>-&gt;<CODE> </CODE>float_matrix<CODE> </CODE>-&gt;<CODE> </CODE>float_matrix<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>"matrix_add"</CODE><CODE> </CODE>;;<BR># <B>external</B><CODE> </CODE>prod<CODE> </CODE><CODE>:</CODE><CODE> </CODE>float_matrix<CODE> </CODE>-&gt;<CODE> </CODE>float_matrix<CODE> </CODE>-&gt;<CODE> </CODE>float_matrix<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>"matrix_product"</CODE><CODE> </CODE>;;<BR>

</PRE>

</span><script language="JavaScript"><!--
  closePopUp("16_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script></OL><A NAME="toc165"></A>
<H3> Counting Words: Main Program in C</H3>
The Unix command <TT>wc</TT> counts the number of characters, words
and lines in a file. The goal of this exercise is to implement this
command, while counting repeated words only once.
<OL type=1>
<LI>
 Write the program <TT><A id="a244__17_APPEND/ICcor.ml.tex" href="javascript: void showMessage('17_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 17,APPEND/ICcor.ml.tex,wc-progC -->wc</SPAN></A></TT> in C. This 
program will simply count words, lines and characters in the file
whose name is passed on the command line.
<!-- POPUP DEFINITION -->
<layer id="l__17_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","17_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 Le fichier <TT>wc.c</TT> :
<PRE>
#include &lt;stdio.h&gt;

void read_file (char *path) {
  FILE *fd=fopen(path,"r");
  int chr=0;
  char buffer[80], *buff;
  int num_chr=0, nun_words=0, num_lines=0;

  if (fd == NULL) exit(2) ;
  buff=buffer ; *buff=0 ;
  while ((chr=getc(fd))!=EOF) {
    num_chr++ ;
    if (chr=='\n') num_lines++ ;
    if (chr==' ' || chr=='\n' ||(buff-buffer)&gt;=80) {
      if (buff!=buffer) { num_words++; *buff=0; buff=buffer; }
    }
    else *(buff++)=chr; 
  }
  printf(" %d - %d - %d : %s\n",num_lines,num_words,num_chr,path);
}

int main (int argc,char **argv)
{
  if (argc&gt;1) read_file(argv[1]);
  return 0;
}
</PRE></span><script language="JavaScript"><!--
  closePopUp("17_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script><BR>
<BR>

<LI> Write in Objective CAML a function
<TT><A id="a245__18_APPEND/ICcor.ml.tex" href="javascript: void showMessage('18_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 18,APPEND/ICcor.ml.tex,wc-addword -->add_word</SPAN></A></TT>  
that uses a hash table to record how many times the
function was invoked with the same character string as argument.
<!-- POPUP DEFINITION -->
<layer id="l__18_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","18_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 

<PRE><BR># <B>let</B><CODE> </CODE>table<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Hashtbl.create<CODE> </CODE><CODE>1</CODE><CODE>7</CODE><CODE> </CODE>;;<BR><CODE>val table : ('_a, '_b) Hashtbl.t = &lt;abstr&gt;</CODE><BR><BR># <B>let</B><CODE> </CODE>add_word<CODE> </CODE><TT>(</TT>w<CODE>:</CODE>string<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>try</B><CODE> </CODE><B>let</B><CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Hashtbl.find<CODE> </CODE>table<CODE> </CODE>w<CODE> </CODE><B>in</B><CODE> </CODE>incr<CODE> </CODE>p<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>with</B><CODE> </CODE>Not_found<CODE> </CODE>-&gt;<CODE> </CODE>Hashtbl.add<CODE> </CODE>table<CODE> </CODE>w<CODE> </CODE><TT>(</TT>ref<CODE> </CODE><CODE>1</CODE><TT>)</TT><CODE> </CODE>;;<BR><CODE>val add_word : string -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>

</span><script language="JavaScript"><!--
  closePopUp("18_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script><BR>
<BR>

<LI> Write two <A id="a246__19_APPEND/ICcor.ml.tex" href="javascript: void showMessage('19_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 19,APPEND/ICcor.ml.tex,wc-countword -->functions</SPAN></A>  
<TT>num_repeated_words</TT> and <TT>num_unique_words</TT> counting
respectively the number of word repetitions and the number of unique
words, as determined from the hash table built by <TT>add_word</TT>.
<!-- POPUP DEFINITION -->
<layer id="l__19_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","19_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 

<PRE><BR># <B>let</B><CODE> </CODE>num_repeated_words<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>i<CODE> </CODE><CODE>=</CODE><CODE> </CODE>ref<CODE> </CODE><CODE>0</CODE><CODE> </CODE><B>in</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>Hashtbl.iter<CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE><CODE>_</CODE><CODE> </CODE>n<CODE> </CODE><CODE> </CODE>-&gt;<CODE> </CODE><B>if</B><CODE> </CODE><CODE>!</CODE>n<CODE>&gt;</CODE><CODE>1</CODE><CODE> </CODE><B>then</B><CODE> </CODE>incr<CODE> </CODE>i<TT>)</TT><CODE> </CODE>table<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>!</CODE>i<CODE> </CODE>;;<BR><CODE>val num_repeated_words : unit -&gt; int = &lt;fun&gt;</CODE><BR><BR># <B>let</B><CODE> </CODE>num_unique_words<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>i<CODE> </CODE><CODE>=</CODE><CODE> </CODE>ref<CODE> </CODE><CODE>0</CODE><CODE> </CODE><B>in</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>Hashtbl.iter<CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE><CODE>_</CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE><CODE> </CODE>-&gt;<CODE> </CODE>incr<CODE> </CODE>i<TT>)</TT><CODE> </CODE>table<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>!</CODE>i<CODE> </CODE>;;<BR><CODE>val num_unique_words : unit -&gt; int = &lt;fun&gt;</CODE><BR>

</PRE>

</span><script language="JavaScript"><!--
  closePopUp("19_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script><BR>
<BR>

<LI> <A id="a247__20_APPEND/ICcor.ml.tex" href="javascript: void showMessage('20_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 20,APPEND/ICcor.ml.tex,wc-register -->Register</SPAN></A> the three previous functions 
so that they can be called from a C program.
<!-- POPUP DEFINITION -->
<layer id="l__20_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","20_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 

<PRE><BR># Callback.register<CODE> </CODE><CODE>"add word"</CODE><CODE> </CODE>add_word<CODE> </CODE>;<BR><CODE> </CODE>Callback.register<CODE> </CODE><CODE>"rep words"</CODE><CODE> </CODE>num_repeated_words<CODE> </CODE>;<BR><CODE> </CODE>Callback.register<CODE> </CODE><CODE>"uni words"</CODE><CODE> </CODE>num_unique_words<CODE> </CODE>;<BR>

</PRE>

</span><script language="JavaScript"><!--
  closePopUp("20_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script><BR>
<BR>

<LI> Rewrite the <A id="a248__21_APPEND/ICcor.ml.tex" href="javascript: void showMessage('21_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 21,APPEND/ICcor.ml.tex,wc-read -->main function</SPAN></A> of the 
<TT>wc</TT> program so that it prints the number of unique words instead of
the number of words.
<!-- POPUP DEFINITION -->
<layer id="l__21_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","21_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 We must include the following header files:
<PRE>
#include &lt;caml/mlvalues.h&gt;
#include &lt;caml/callback.h&gt;
</PRE><PRE>
void read_file (char *path) {
  FILE *fd = fopen(path,"r") ;
  int chr=0 ;
  char buffer[80],*buff ;
  int num_chr=0, num_words, num_lines=0;

  if (fd == NULL) exit(2) ;
  buff=buffer; *buff=0;
  while ((chr=getc(fd))!=EOF) {
    num_chr++ ;
    if (chr=='\n') num_lines++ ;
    if (chr==' ' || chr=='\n' ||(buff-buffer)&gt;=80) {
      if (buff!=buffer) { 
 *buff=0;
 buff=buffer;
 callback(*caml_named_value("add word"),copy_string(buffer));
      }
    }
    else *(buff++)=chr; 
  }
  num_words=Int_val(callback(*caml_named_value("uni words"),Val_unit)); 
  printf(" %d - %d - %d : %s\n",num_lines,num_words,num_chr,path);
}
</PRE></span><script language="JavaScript"><!--
  closePopUp("21_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script><BR>
<BR>

<LI> Write the <TT><A id="a249__22_APPEND/ICcor.ml.tex" href="javascript: void showMessage('22_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 22,APPEND/ICcor.ml.tex,wc-caml -->main</SPAN></A></TT> function and the 
commands required to compile this program as an Objective CAML program.
<!-- POPUP DEFINITION -->
<layer id="l__22_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","22_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 <PRE>
int main (int argc,char **argv)
{
  caml_main(argv);
  if (argc&gt;1) read_file(argv[1]);
  return 0;
}
</PRE>Compiling to bytecode:
<PRE>
$ cc -c -I /usr/local/lib/ocaml/ wc.c
$ ocamlc -custom words.ml wc.o
</PRE>Compiling to native code:
<PRE>
$ cc -c -I /usr/local/lib/ocaml/ wc.c
$ ocamlopt words.ml wc.o
</PRE></span><script language="JavaScript"><!--
  closePopUp("22_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script><BR>
<BR>

<LI> Write the <TT><A id="a250__23_APPEND/ICcor.ml.tex" href="javascript: void showMessage('23_APPEND/ICcor.ml.tex')" class="mousable"><SPAN style=""><!-- 23,APPEND/ICcor.ml.tex,wc-c -->main</SPAN></A></TT> function and the 
commands required to compile this program as a C program.
<!-- POPUP DEFINITION -->
<layer id="l__23_APPEND/ICcor.ml.tex" class="hint" style="visibility:hidden; position:absolute" visibility="hide"  width="50%">
<script language="JavaScript"><!--
  openPopUp("50%","23_APPEND/ICcor.ml.tex","");
// --></script><span style="">
 <PRE>
int main (int argc,char **argv)
{
  caml_startup(argv);
  if (argc&gt;1) read_file(argv[1]);
  return 0;
}
</PRE>Compiling to bytecode:
<PRE>
$ ocamlc -output-obj words.ml -o words.o
$ gcc -c -I /usr/local/lib/ocaml/ wc.c
$ gcc words.o wc.o -L /usr/local/lib/ocaml/ -lcamlrun -lcurses
</PRE>Compiling to native code:
<PRE>
$ ocamlopt -output-obj words.ml -o wordsnat.o 
$ gcc -c -I /usr/local/lib/ocaml/ wc.c
$ gcc wordsnat.o wc.o -L /usr/local/lib/ocaml/ -lasmrun 
</PRE></span><script language="JavaScript"><!--
  closePopUp("23_APPEND/ICcor.ml.tex");
// --></script></layer><!-- END OF POPUP -->
<script language="JavaScript"><!--
  initializePreviousHints();
// --></script></OL> <HR>
<A HREF="book-ora118.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora120.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
